import { Context, Next } from 'koa';
import * as jwt from 'jsonwebtoken';
import { getRedisClient } from '../database/redis';
import config from '../config';
import { error } from '../utils/response';
import { ResponseCode } from '../config/responseCode';
import { queryOne } from '../database/mysql';
import { User } from '../database/models';

/**
 * JWT Token Payload
 */
export interface TokenPayload {
  userId: string;
  username: string;
  isAdmin: number;
}

/**
 * 生成Token
 */
export function generateToken(payload: TokenPayload): string {
  return jwt.sign(payload as object, config.jwt.secret, {
    expiresIn: config.jwt.expiresIn,
  } as jwt.SignOptions);
}

/**
 * 验证Token
 */
export function verifyToken(token: string): TokenPayload | null {
  try {
    return jwt.verify(token, config.jwt.secret) as TokenPayload;
  } catch (err) {
    return null;
  }
}

/**
 * 将Token存储到Redis
 */
export async function setTokenToRedis(userId: string, token: string): Promise<void> {
  const redis = getRedisClient();
  const key = `token:${userId}`;
  await redis.setex(key, config.token.expiresIn, token);
}

/**
 * 从Redis获取Token
 */
export async function getTokenFromRedis(userId: string): Promise<string | null> {
  const redis = getRedisClient();
  const key = `token:${userId}`;
  return redis.get(key);
}

/**
 * 检查Token是否在黑名单
 */
export async function isTokenBlacklisted(token: string): Promise<boolean> {
  const redis = getRedisClient();
  const key = `blacklist:${token}`;
  const result = await redis.exists(key);
  return result === 1;
}

/**
 * 将Token加入黑名单
 */
export async function addTokenToBlacklist(token: string, expiresIn: number): Promise<void> {
  const redis = getRedisClient();
  const key = `blacklist:${token}`;
  await redis.setex(key, expiresIn, '1');
}

/**
 * 删除Token（登出）
 */
export async function removeToken(userId: string): Promise<void> {
  const redis = getRedisClient();
  const key = `token:${userId}`;
  await redis.del(key);
}

/**
 * 认证中间件
 */
export async function authMiddleware(ctx: Context, next: Next): Promise<void> {
  const body = ctx.request.body as { token?: string } | undefined;
  const token = ctx.get('Authorization')?.replace('Bearer ', '') || 
                body?.token ||
                (ctx.query.token as string | undefined);
  
  if (!token) {
    error(ctx, ResponseCode.UNAUTHORIZED);
    return;
  }

  // 检查Token是否在黑名单
  const isBlacklisted = await isTokenBlacklisted(token);
  if (isBlacklisted) {
    error(ctx, ResponseCode.TOKEN_INVALID);
    return;
  }

  // 验证Token
  const payload = verifyToken(token);
  if (!payload) {
    error(ctx, ResponseCode.TOKEN_INVALID);
    return;
  }

  // 检查Redis中的Token
  const redisToken = await getTokenFromRedis(payload.userId);
  if (!redisToken || redisToken !== token) {
    error(ctx, ResponseCode.TOKEN_INVALID);
    return;
  }

  // 获取用户信息
  const user = await queryOne<User>('SELECT * FROM users WHERE id = ? AND status = 1', [payload.userId]);
  if (!user) {
    error(ctx, ResponseCode.USER_NOT_FOUND);
    return;
  }

  // 将用户信息存储到state
  ctx.state.user = user;
  ctx.state.tokenPayload = payload;

  await next();
}

/**
 * 管理员权限中间件
 */
export async function adminMiddleware(ctx: Context, next: Next): Promise<void> {
  const user = ctx.state.user as User;
  
  if (!user || user.is_admin !== 1) {
    error(ctx, ResponseCode.PERMISSION_DENIED);
    return;
  }

  await next();
}

